import os
import sys
import time

import django
import requests
from lxml import etree

BASE_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))

sys.path.append(BASE_DIR)

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'music_project.settings')
django.setup()
from music.models import Genre, MusicDetail, MusicCollection, MusicClick


class BaiYueMi:
    def __init__(self):
        self.base_url = "https://bailemi.com/song/tag"
        self.headers = {
            "X-Requested-With": "XMLHttpRequest"
        }
        self.query_url = "https://www.yeyulingfeng.com/tools/music/"
        self.lrc_path = os.path.join(BASE_DIR, "files/lrc")
        self.audio_path = os.path.join(BASE_DIR, "files/audio")

    def lrc_save(self, music_id, lrc_content):
        file_name = f"{music_id}.lrc"
        save_path = os.path.join(self.lrc_path, file_name)

        try:
            with open(save_path, 'w', encoding='utf-8') as file:
                file.write(lrc_content)
            print(f"LRC file saved: {save_path}")
        except IOError as e:
            # 文件写入出错
            print(f"Failed to save LRC file: {e}")
        return save_path

    def audio_save(self, music_id, url):
        file_name = f"{music_id}.mp3"
        save_path = os.path.join(self.audio_path, file_name)
        response = requests.get(url, stream=True)
        if response.status_code == 200:
            # 打开一个文件用于写入二进制数据
            with open(save_path, 'wb') as file:
                # 写入文件
                for chunk in response.iter_content(chunk_size=128):
                    file.write(chunk)
            print(f"File downloaded and saved as {save_path}")
        else:
            print("Failed to download the file")

        return save_path

    def music_title(self, page_url, genre_id):
        music_page_html = requests.get(url=page_url).text
        tree = etree.HTML(music_page_html)
        if not tree:
            time.sleep(5)
            return self.music_title(page_url, genre_id)
        music_titles = tree.xpath('//ul[@class="s_lsongs_child"]//li//div[@class="art_details"]//a/text()')
        for music_title in music_titles:
            print(music_title)
            form_data = {
                "input": music_title,
                "filter": "name",
                "type": "netease",
                "page": 1
            }
            music_details = requests.post(url=self.query_url, data=form_data, headers=self.headers).json()

            if music_details:
                music_details = music_details.get("data", [])
            else:
                music_details = []
            for music_detail in music_details:
                if not music_detail.get("url"):
                    continue

                # 检查音频 是否已经存在
                title = music_detail.get("title", "")
                if MusicDetail.objects.filter(name=title).exists():
                    print(f"Music with title {title} already exists. Skipping...")
                    continue
                audio_url = music_detail.get("url", "")
                music_obj = MusicDetail()
                music_obj.name = music_detail.get("title", "")
                music_obj.pic_url = music_detail.get("pic", "").split("?")[0]
                music_obj.author = music_detail.get("author", "")
                music_obj.audio_url = audio_url
                music_obj.genre_id = genre_id
                music_obj.save()

                music_id = music_obj.id
                lrc_path = self.lrc_save(music_id, music_detail.get("lrc", ""))
                audio_path = self.audio_save(music_id, audio_url)

                music_obj = MusicDetail.objects.get(id=music_id)
                music_obj.audio_path = audio_path
                music_obj.lrc_path = lrc_path
                music_obj.save()
                # 只保存第一首
                break

    def music_type(self):
        res_html = requests.get(url=self.base_url).text
        tree = etree.HTML(res_html)
        # 网站不稳定则等待重复爬取
        if not tree:
            time.sleep(5)
            return self.music_type()
        hrefs = tree.xpath('//div[@class="genre_lst"]/a/@href')
        print(hrefs)
        for href in hrefs:
            music_type = href.split("?tags=")[-1]
            def page_urls_details():
                page_html = requests.get(url=href).text
                page_tree = etree.HTML(page_html)
                # 网站不稳定则等待重复爬取
                if not page_tree:
                    time.sleep(5)
                    return page_urls_details()
                page_urls = page_tree.xpath('//div[@class="page"]//a[@title="尾页"]/@href')
                return page_urls

            page_urls = page_urls_details()
            if not page_urls:
                print(f"No page URL found for {href}. Skipping...")
                continue

            page_url = page_urls[0]
            print(page_url)
            page_num = page_url.split("page=")[-1].split("&")[0]

            try:
                page_num = int(page_num)
            except ValueError:
                page_num = 1

            if not Genre.objects.filter(href=href).exists():
                genre_obj = Genre()
                genre_obj.name = music_type
                genre_obj.href = href
                genre_obj.save()
            else:
                genre_obj = Genre.objects.filter(href=href).first()
            # for page_index in range(1, page_num + 1):
            #     music_url = f"{href}&page={page_index}"
            #     self.music_title(music_url, genre_obj.id)
            # 每种类型中只爬取第一页
            music_url = f"{href}&page=1"
            self.music_title(music_url, genre_obj.id)

    def music_detail(self):
        pass

    def music_data_init(self):
        # 删除所有 Genre 数据
        Genre.objects.all().delete()
        print("All Genre data has been deleted.")

        # 删除所有 MusicDetail 数据
        MusicDetail.objects.all().delete()
        print("All MusicDetail data has been deleted.")

        # 删除所有 MusicCollection 数据
        MusicCollection.objects.all().delete()
        print("All MusicCollection data has been deleted.")

        # 删除所有 MusicClick 数据
        MusicClick.objects.all().delete()
        print("All MusicClick data has been deleted.")

bym = BaiYueMi()
bym.music_data_init()
bym.music_type()

